package com.songxh.core.utils;


import com.songxh.core.entity.UserContext;
import com.songxh.core.enums.BizCodeEnum;
import com.songxh.core.exception.BizException;
import com.songxh.core.shared.constant.RedisConsts;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * jwt工具类
 * @author songxh
 * @create 2022-12-20-19:37
 */
public class JWTUtils {

    //加密盐
    private static String jwtSecret = "songxh_gra_pro";

    /**
     *生成token
     * @param claims
     * @param jwtId
     * @return
     */
    public static String creatJWTToken(Map<String, Object> claims, String jwtId){
        //指定签名的时候使用签名算法，header部分，jjwt已经封装好
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        Map<String,Object> header = new HashMap<String,Object>();
        header.put("alg","HS256");
        header.put("typ","JWT");

        JwtBuilder jwtBuilder = Jwts.builder()
                .setClaims(claims)  //载荷卸写在最前面 避免被覆盖，存入账号与id，存redis以及从redis取数据时需要
                .setId(jwtId) //jwt的id 一个不重复的值即可 使用uuid
                .setIssuedAt(new Date(System.currentTimeMillis()))  //签发时间
                .setHeader(header)
                .signWith(signatureAlgorithm, jwtSecret) //签名使用签名算法和密钥
                .setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 60 * 1000));//一天的过期时间

        String token = jwtBuilder.compact();
        return token;
    }

    /**
     * 校验token
     * @param token
     * @return
     */
    public static Claims checkToken(String token){
        Claims claims;
        try {
            claims = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody();
            return claims;
        }catch (Exception e){
            claims = null;
        }
        return claims;
    }

    /**
     * 刷新缓存，刷新过期时间
     * @param account
     * @param userId
     * @param expireTime
     */
    public static void refreshToken(String account, Long userId, Long expireTime){
        String accessTokenKey = String.format(RedisConsts.S_Token_ACCESS_KEY, account, userId);
        String token = RedisUtils.get(accessTokenKey, String.class);
        if (StringUtils.isEmpty(token)){
            throw new BizException(BizCodeEnum.ACCESS_TOKEN_EXPIRE.getMsg());
        }
        if (expireTime == null){
            expireTime = RedisConsts.DEFAULT_TOKEN_EXPIRE_TIME_SECONDS;
        }
        RedisUtils.set(accessTokenKey, token, expireTime.intValue());
    }

    /**
     * 刷新最后登录时间
     * @param account
     * @param userId
     * @param
     */
    public static void refreshLoinTime(String account, Long userId, String nowTime){
        String userInfoKey = String.format(RedisConsts.S_USER_INFO_KEY, account, userId);
        UserContext userContext = RedisUtils.get(userInfoKey, UserContext.class);
        if (userContext == null){
            throw new BizException(BizCodeEnum.USER_INFO_NOT_EXIST.getMsg());
        }
        userContext.setLastLogin(nowTime);
        RedisUtils.set(userInfoKey, userContext, RedisConsts.DEFAULT_EXPIRE_TIME_SECONDS);

    }
}
